package com.ljj.examisto.ui.dialog

import android.content.Context
import android.text.Editable
import android.text.InputFilter
import android.text.TextWatcher
import android.view.Window
import android.widget.NumberPicker
import com.ljj.examisto.R
import com.ljj.examisto.databinding.DialogScrollingTimePickerBinding
import com.ljj.examisto.ui.base.BaseDialog

class ScrollingTimePickerDialog(
    context: Context,
    private val onTimeSetListener: (Int, Int) -> Unit
) : BaseDialog(context, R.style.RightSlideDialog) {
    companion object {
        private const val MIN_HOUR = 0
        private const val MAX_HOUR = 99
        private const val MIN_MINUTE = 0
        private const val MAX_MINUTE = 59
    }

    private var binding: DialogScrollingTimePickerBinding

    init {
        requestWindowFeature(Window.FEATURE_NO_TITLE)
        binding = DialogScrollingTimePickerBinding.inflate(layoutInflater)
        setContentView(binding.root)
        setupNumberPickers()
        setupEditTexts()
        setupButton()
    }

    private fun setupNumberPickers() {
        with(binding.npHour) {
            minValue = MIN_HOUR
            maxValue = MAX_HOUR
            value = MIN_HOUR
            wrapSelectorWheel = true
            setOnValueChangedListener { _, _, newVal ->
                binding.etHour.setText(newVal.toString())
            }
        }
        with(binding.npMinute) {
            minValue = MIN_MINUTE
            maxValue = MAX_MINUTE
            value = MIN_MINUTE
            wrapSelectorWheel = true
            setOnValueChangedListener { _, _, newVal ->
                binding.etMinute.setText(newVal.toString())
            }
        }
    }

    private fun setupEditTexts() {
        binding.etHour.filters = arrayOf(createInputFilter(MIN_HOUR, MAX_HOUR))
        binding.etMinute.filters = arrayOf(createInputFilter(MIN_MINUTE, MAX_MINUTE))
        binding.etHour.addTextChangedListener(createTextWatcher(binding.npHour, MAX_HOUR))
        binding.etMinute.addTextChangedListener(createTextWatcher(binding.npMinute, MAX_MINUTE))
    }

    private fun setupButton() {
        binding.btnConfirm.setOnClickListener {
            onTimeSetListener(binding.npHour.value, binding.npMinute.value)
            dismiss()
        }
    }

    private fun createInputFilter(minValue: Int, maxValue: Int): InputFilter {
        return InputFilter { source, start, end, dest, dstart, dend ->
            val inputText = dest.subSequence(0, dstart).toString() +
                    source.subSequence(start, end) +
                    dest.subSequence(dend, dest.length).toString()
            if (inputText.isEmpty() ||
                (inputText.matches(Regex("\\d+")) && inputText.toInt() in minValue..maxValue)) {
                null  // 允许输入
            } else {
                ""    // 拒绝输入
            }
        }
    }

    /**
     * 创建一个TextWatcher用于监听EditText的输入，并将其转换为NumberPicker的值
     * @param picker NumberPicker
     * @param maxValue 最大值
     * @return TextWatcher
     */
    private fun createTextWatcher(picker: NumberPicker, maxValue: Int): TextWatcher {
        return object : TextWatcher {
            override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
            override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
                val value = s?.toString()?.takeIf { it.isNotEmpty() }?.toIntOrNull()
                if (value != null) {
                    picker.value = value.coerceIn(0, maxValue)
                } else {
                    picker.value = picker.minValue
                }
            }
            override fun afterTextChanged(s: Editable?) {}
        }
    }

    fun setDefaultHour(hour: Int) {
        val validHour = hour.coerceIn(MIN_HOUR, MAX_HOUR)
        binding.npHour.value = validHour
        binding.etHour.setText(validHour.toString())
    }

    fun setDefaultMinute(minute: Int) {
        val validMinute = minute.coerceIn(MIN_MINUTE, MAX_MINUTE)
        binding.npMinute.value = validMinute
        binding.etMinute.setText(validMinute.toString())
    }

    fun setDefaultTime(hour: Int, minute: Int) {
        setDefaultHour(hour)
        setDefaultMinute(minute)
    }
}